iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 11
0

昨天我們有了很基本的 Model 雛形,實作下去會發現其實不難理解,說來說去都離不開物件導向的概念,透過實作的過程,可以慢慢了解 ORM 的原理是什麼,如果還是有點模糊,沒關係,今天我們會繼續規劃其他功能,透過一天一天的實作,來加深更堅固的印象

話不多說直接進入主題吧

找出所有的資料

除了做 find 查詢,另一個很常用的是 all,很常會看到在 Action 裡面搭配 index 一起使用,現在就來看看怎麼實作 all 的功能

# mavericks/lib/mavericks/file_model.rb

def self.all
  files = Dir['db/tasks/*.json']
  files.map { |f| FileModel.new f}
end

我們透過 Dir 來將 tasks 的 JSON 格式檔案,用 * 全部取出來,然後搭配 map,生成一個一個的物件

接著回到 just_do 我們就可以這樣使用

# just_do/app/controller/tasks_controller.rb

class TasksController < Mavericks::Controller
  def index
    @tasks = FileModel.all
  end

  def show
    @task = FileModel.find(1)
  end
end

為了可以 Demo 找出所有資料的功能,需要新增多一點資料

# just_do/db/tasks/2.json

{
  "title": "吃好睡飽",
  "content": "每天都有滷肉飯吃"
}

再修改一下 view 的部分

<!-- just_do/app/views/tasks/index.html.erb -->

<% @tasks.each do |task| %>
  <div class="row">
    <div class="col-sm-6 col-lg-3">
      <div class="card">
        <h5 class="card-header"><%= task['title'] %></h5>
        <div class="card-body">
          <p class="card-text"><%= task['content'] %></p>
          <span><a href="/tasks/1/edit">修改</a><a data-confirm="確定刪除?" rel="nofollow" data-method="delete" href="/tasks/1">刪除</a></span>
        </div>
      </div>
    </div>
  </div>
<% end %>

沒有意外的話,畫面上應該會出現兩筆資料,代表成功了!

新增一筆資料

剛剛相信大家應該都是手動新增第二筆資料,但如果要靠 Model 來新增呢?新增資料會稍微麻煩一點,除了要處理新增的內容以外,因為我們是用 JSON 格式檔案來代替資料庫,並不是用傳統的 SQL 語法來新增資料,所以我們其實在處理的是 要怎麼寫入一個 json 檔案

那接下來我們先在 class FileModel 底下繼續實作一個 create

# mavericks/lib/mavericks/file_model.rb

require "multi_json"
require 'byebug'

module Mavericks
  module Model
    class FileModel
      # .
      # .
      # (略)
      def self.create(attrs)
        hash = {}
        hash[:title] = attrs[:title] || ""
        hash[:content] = attrs[:content] || ""

        files = Dir["db/tasks/*.json"]
        id = files.map { |f| f.split('/')[-1].gsub('.json','').to_i }.max + 1

         File.open("db/tasks/#{id}.json", "w") do |f|
           f.write <<-TEMPLATE
              {
               "title": "#{hash[:title]}",
               "content": "#{hash[:content]}"
              }
           TEMPLATE
         end

         FileModel.new "db/tasks/#{id}.json"
      end
    end
  end
end

有沒有發現我們一直都用 self?那是因為我們現在都是在實作 class method

這裡說明一下實作的過程,我們在 create 裡面建立了一個 hash 來接收新增的值

hash = {}
hash[:title] = attrs[:title] || ""
hash[:content] = attrs[:content] || ""

接著尋找 db/task 底下所有的 json 檔案,然後利用 f.split('/') 後的結果,並且用 [-1] 取得陣列最後一個值,也就是 1.json 之類的檔名,之後透過 gsub 用正規表達式把 .json 去掉只留下 id,最後在 [1, 2, 3...] 的陣列裡面,取得 max 並且 + 1,就是新檔案的 ID

files = Dir["db/tasks/*.json"]
id = files.map { |f| f.split('/')[-1].gsub('.json','').to_i }.max + 1

最後利用新的 ID 來新增一個檔案,搭配 Ruby 的 Heredoc 來定義多行字串,建立 template 內容,並且寫入檔案

File.open("db/tasks/#{id}.json", "w") do |f|
  f.write <<-TEMPLATE
    {
     "title": "#{hash[:title]}",
     "content": "#{hash[:content]}"
    }
  TEMPLATE
end

FileModel.new "db/tasks/#{id}.json"

回到 just_do 來測試結果,在 Controller 底下,建立一個新的 Action 來處理新增資料

# just_do/app/controllers/tasks_controller.rb

def create
  attrs = {
    title: '週末跟朋友聚餐',
    content: '喝酒喝到飽'
  }

  FileModel.create(attrs)
  @tasks = FileModel.all
  render 'index'
end

就跟平常使用 Rails很像,用 Hash 搭配 FileModel.create 來完成新增資料的動作,最後 render Index 頁面,記得在這之前要建立 @tasks,因為我們在 index.html.erb 的頁面有用到 @tasks

完成後一樣打開伺服器看看結果,現在只要每次瀏覽一次 http://127.0.0.1:3001/tasks/create,就會建立一筆新的 JSON 檔案!

開發者說...

「不是呀,我記得新增應該要有個表格讓我填資料才對,不是像這樣子重整就可以新增一筆資料,而且一直重整還會一直增加..」

是的,因為我們還沒處理到,怎麼接受表單 POST 過來的資料,還記得在 Rails 當中會依照 HTTP request methods 來處理相對應的行為嗎?接下來的文章我們將會開始談到這塊


上一篇
[DAY 10] 復刻 Rails - MVC 的最後一張拼圖 - Model
下一篇
[DAY 12] 復刻 Rails - Request
系列文
向 Rails 致敬!30天寫一個網頁框架,再拿來做一個 Todo List30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言